export const Ease = {
    linear: (r) => r,
    sine: (r) => Math.sin(r * Math.PI / 2),
    easeInOut: (r) => 6 * r ** 5 - 15 * r ** 4 + 10 * r ** 3,
    easeIn: (r) => Math.sqrt(r),
    easeOut: (r) => r ** 3,
    easeLate: (r) => 1 - Math.sqrt(1 - Math.sqrt(r)),
};
/**
 * 动画运动类
 * 管理对象的动画过渡效果
 * @template T 动画对象类型
 */
export class Motion {
    obj;
    duration;
    from;
    to;
    ease;
    id;
    rate;
    vars;
    resolve;
    wait;
    constructor(obj, duration, from, to, ease) {
        this.obj = obj;
        this.duration = duration;
        this.from = from;
        this.to = to;
        this.ease = ease;
        this.id = Symbol();
        this.rate = 0;
        this.vars = [];
        this.wait = new Promise(resolve => this.resolve = resolve);
        for (const key in this.from) {
            if (typeof this.from[key] !== typeof this.to[key]) {
                continue;
            }
            if (typeof this.to[key] !== "number") {
                continue;
            }
            this.vars.push(key);
        }
    }
    update(dt) {
        this.rate += dt;
        const rate = this.rate / this.duration;
        if (rate >= 1) {
            Motion.remove(this.id);
            this.resolve?.();
            for (const key in this.to) {
                this.obj[key] = this.to[key];
            }
            return;
        }
        for (const key of this.vars) {
            const from = this.from[key];
            const delta = (this.to[key] - from) * this.ease(rate);
            this.obj[key] = from + delta;
        }
    }
    resume() {
        Motion.add(this, this.id);
    }
    pause() {
        Motion.remove(this.id);
    }
    static motions = new Map();
    static add(m, id) {
        this.motions.set(id, m);
    }
    static remove(id) {
        this.motions.delete(id);
    }
    static fromTo(obj, duration, from, to, ease = Ease.linear) {
        const m = new Motion(obj, duration, from, to, ease);
        Motion.add(m, m.id);
        return m;
    }
    static update(dt) {
        for (const [id, m] of this.motions) {
            m.update(dt);
        }
    }
}
;
(function () {
    setInterval(() => {
        Motion.update(4);
    }, 4);
})();